package 遍历器;

import 抽象语法树节点.*;

public class 抽象语法树基础遍历器 {
    public 抽象语法树基础遍历器(抽象语法树基础监听器 监听器) {
        this.监听器 = 监听器;
    }

    private final 抽象语法树基础监听器 监听器;

    public void 遍历(抽象语法树 节点) {
        if (节点 instanceof Super访问器 super访问器) {
            遍历(super访问器);
        } else if (节点 instanceof This访问器 this访问器) {
            遍历(this访问器);
        } else if (节点 instanceof 代码块 代码块) {
            遍历(代码块);
        } else if (节点 instanceof 函数调用 函数调用) {
            遍历(函数调用);
        } else if (节点 instanceof 加法表达式 加法表达式) {
            遍历(加法表达式);
        } else if (节点 instanceof 参数列表 参数列表) {
            遍历(参数列表);
        } else if (节点 instanceof 参数定义 参数定义) {
            遍历(参数定义);
        } else if (节点 instanceof 变量定义 变量定义) {
            遍历(变量定义);
        } else if (节点 instanceof 字段定义 字段定义) {
            遍历(字段定义);
        } else if (节点 instanceof 成员访问 成员访问) {
            遍历(成员访问);
        } else if (节点 instanceof 整型字面量 整型字面量) {
            遍历(整型字面量);
        } else if (节点 instanceof 方法定义 方法定义) {
            遍历(方法定义);
        } else if (节点 instanceof 方法调用 方法调用) {
            遍历(方法调用);
        } else if (节点 instanceof 标识符 标识符) {
            遍历(标识符);
        } else if (节点 instanceof 类定义 类定义) {
            遍历(类定义);
        } else if (节点 instanceof 编译单元 编译单元) {
            遍历(编译单元);
        } else if (节点 instanceof 表达式列表 表达式列表) {
            遍历(表达式列表);
        } else if (节点 instanceof 赋值语句 赋值语句) {
            遍历(赋值语句);
        } else if (节点 instanceof 返回语句 返回语句) {
            遍历(返回语句);
        } else {
            throw new RuntimeException("不支持的节点类型");
        }
    }


    //以下排序方式就参考在Idea中文件的排序

    private void 遍历(Super访问器 节点) {
        监听器.进入Super访问器(节点);
        监听器.离开Super访问器(节点);
    }

    private void 遍历(This访问器 节点) {
        监听器.进入This访问器(节点);
        监听器.离开This访问器(节点);
    }

    private void 遍历(代码块 节点) {
        监听器.进入代码块(节点);

        if (节点.子节点 != null) {
            for (var 子节点 : 节点.子节点) {
                遍历(子节点);
            }
        }

        监听器.离开代码块(节点);
    }

    private void 遍历(函数调用 节点) {
        监听器.进入函数调用(节点);

        遍历(节点.对象);
        if (节点.参数列表 != null) {
            遍历(节点.参数列表);
        }

        监听器.离开函数调用(节点);
    }

    private void 遍历(加法表达式 节点) {
        监听器.进入加法表达式(节点);
        遍历(节点.左操作数);
        遍历(节点.右操作数);
        监听器.离开加法表达式(节点);
    }

    private void 遍历(参数列表 节点) {
        监听器.进入参数列表(节点);

        if (节点.参数 != null) {
            for (var 参数 : 节点.参数) {
                遍历(参数);
            }
        }

        监听器.离开参数列表(节点);
    }

    private void 遍历(参数定义 节点) {
        监听器.进入参数定义(节点);
        监听器.离开参数定义(节点);
    }

    private void 遍历(变量定义 节点) {
        监听器.进入变量定义(节点);

        if (节点.初值 != null) {
            遍历(节点.初值);
        }

        监听器.离开变量定义(节点);
    }

    private void 遍历(字段定义 节点) {
        监听器.进入字段定义(节点);

        if (节点.初值 != null) {
            遍历(节点.初值);
        }

        监听器.离开字段定义(节点);
    }

    private void 遍历(成员访问 节点) {
        监听器.进入成员访问(节点);
        遍历(节点.对象);
        监听器.离开成员访问(节点);
    }

    private void 遍历(整型字面量 节点) {
        监听器.进入整型字面量(节点);
        监听器.离开整型字面量(节点);
    }

    private void 遍历(方法定义 节点) {
        监听器.进入方法定义(节点);

        if (节点.参数列表 != null) {
            遍历(节点.参数列表);
        }

        遍历(节点.代码块);

        监听器.离开方法定义(节点);
    }

    private void 遍历(方法调用 节点) {
        监听器.进入方法调用(节点);

        遍历(节点.对象);
        if (节点.参数列表 != null) {
            遍历(节点.参数列表);
        }

        监听器.离开方法调用(节点);
    }

    private void 遍历(标识符 节点) {
        监听器.进入标识符(节点);
        监听器.离开标识符(节点);
    }

    private void 遍历(类定义 节点) {
        监听器.进入类定义(节点);

        for (var 成员 : 节点.成员) {
            遍历(成员);
        }

        监听器.离开类定义(节点);
    }

    private void 遍历(编译单元 节点) {
        监听器.进入编译单元(节点);

        for (var 定义 : 节点.子节点) {
            遍历(定义);
        }

        监听器.离开编译单元(节点);
    }

    private void 遍历(表达式列表 节点) {
        监听器.进入表达式列表(节点);

        if (节点.表达式 != null) {
            for (var 表达式 : 节点.表达式) {
                遍历(表达式);
            }
        }

        监听器.离开表达式列表(节点);
    }

    private void 遍历(赋值语句 节点) {
        监听器.进入赋值语句(节点);
        遍历(节点.左值);
        遍历(节点.右值);
        监听器.离开赋值语句(节点);
    }

    private void 遍历(返回语句 节点) {
        监听器.进入返回语句(节点);

        if (节点.表达式 != null) {
            遍历(节点.表达式);
        }

        监听器.离开返回语句(节点);
    }
}
